﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Linq;
using MS.InformationManagement.Core.Support;
using MS.InformationManagement.Support.Enums;
using Microsoft.SharePoint.Publishing;
using System.Data;
//using MS.InformationManagement.DAL.DTOs;
using MS.InformationManagement.Core.RecordSiteQuery;
using MS.InformationManagement.Support.Constants;
using MS.InformationManagement.Support;
using MS.InformationManagement.DAL.DocumentCenter;
using MS.InformationManagement.DAL.Support;
using Microsoft.SharePoint.Taxonomy;

namespace MS.InformationManagement.BLL.Correspondence
{
    public class DocumentPrinterBLL
    {

        public static IEnumerable<RadicadoBaseSalida> GetLibraryDocuments(string libraryName, int pageIndex, int pageSize, out int totalRecords)
        {
            int startingIndex = pageIndex * pageSize;
            using (DCDocumentCenterDataContext ctx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                var totalDocuments = from radicados in ctx.GetList<RadicadoBaseSalida>(libraryName)
                                     where !radicados.FechaDeImpresión.HasValue &&
                                           (!radicados.Cancelado.HasValue || !radicados.Cancelado.Value) 
                                     select radicados;
                totalRecords = totalDocuments.Count();
                var documents = totalDocuments.Skip(startingIndex).Take(pageSize);
                return documents;
            }
        }

        public static IEnumerable<RadicadoBaseSalida> GetPrintedDocuments(string userName, int pageIndex, int pageSize)
        {
            string libraryName = PeopleHelper.GetPropertyUserProfile(GlobalConstants.UP_DEPARTMENT, userName);
            SPList userLibrary = SPContext.Current.Web.Lists.TryGetList(userName);
            SPList filedLibrary = SPContext.Current.Web.Lists.TryGetList(libraryName);
            DataTable results = getPrintedRadicados(userLibrary.ID.ToString(), filedLibrary.ID.ToString());

            foreach (DataRow currentRow in results.Rows)
            {
                yield return getRadicadoEntity(currentRow);
            }
        }

        public static IEnumerable<RadicadoBaseSalida> GetRecordDocuments(string userName, int pageIndex, int pageSize, out int totalRecords)
        {
            string libraryName = PeopleHelper.GetPropertyUserProfile(MS.InformationManagement.Support.Constants.GlobalConstants.UP_DEPARTMENT, userName);
            IEnumerable<RadicadoBaseSalida> documents = null;
            int startingIndex = pageIndex * pageSize;

            using (var ctx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                documents = (from radicado in ctx.GetList<RadicadoBaseSalida>(libraryName).ScopeToFolder(string.Empty, true)
                             where radicado.TipoRadicado == GlobalConstants.METADATA_TERM_TIPO_RADICADO_SALIDA &&
                                   !radicado.FechaDeImpresión.HasValue
                             select radicado);
                totalRecords = documents.Count();
                documents = documents.Skip(startingIndex).Take(pageSize);
            }

            return documents;
        }

        public static IEnumerable<Radicado> GetRecordPrintedDocuments(string userName, int pageIndex, int pageSize, out int totalRecords)
        {
            int startingIndex = pageIndex * pageSize;
            IEnumerable<Radicado> documents = null;
            string libraryName = PeopleHelper.GetPropertyUserProfile(GlobalConstants.UP_DEPARTMENT, userName);

            using (DCDocumentCenterDataContext ctx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                EntityList<Radicado> targetList = ctx.GetList<Radicado>(libraryName);
                totalRecords = targetList.ScopeToFolder("", true).Count(rad => rad.TipoRadicado.Equals("Radicado Salida") && rad.GetType().GetProperty("FechaDeImpresión").GetValue(rad, null) != null);
                documents = targetList.ScopeToFolder(string.Empty, true).Where(rad => rad.TipoRadicado.Equals("Radicado Salida") && rad.GetType().GetProperty("FechaDeImpresión").GetValue(rad, null) != null).Skip(startingIndex).Take(pageSize);
            }

            return documents;
        }

        public static string SetDocumentPrintDate(string library, int id, string documentType)
        {
            DAL.DocumentCenter.DocumentoImpreso printedRegistry;
            string radPath = string.Empty;
            string path = string.Empty;
            SPFileCollection attachedFiles = null;
            SPFolder foundItem = null;
            printedRegistry = SetPrintDateRadicado(library, id, ref radPath, ref path, ref attachedFiles, ref foundItem);
            return path;
        }

        public static Int32 GetPrintedDocumentsCount(string userName, int pageIndex, int pageSize)
        {

            string libraryName = MS.InformationManagement.Support.PeopleHelper.GetPropertyUserProfile(MS.InformationManagement.Support.Constants.GlobalConstants.UP_DEPARTMENT, userName);

            SPList userLibrary = SPContext.Current.Web.Lists.TryGetList(userName);
            SPList filedLibrary = SPContext.Current.Web.Lists.TryGetList(libraryName);

            CrossListQueryInfo queryInfo = new CrossListQueryInfo();
            queryInfo.Lists = string.Format("<Lists BaseType='1'><List ID='{0}'/><List ID='{1}'/></Lists>", userLibrary.ID, filedLibrary.ID);
            queryInfo.Query = @"<Where><And><Eq><FieldRef Name='Document_Kind'/><Value Type='TaxonomyFieldType'>Radicado Salida</Value></Eq><IsNotNull><FieldRef Name='Document_Printing_Date'/></IsNotNull></And></Where><OrderBy><FieldRef Name='Document_Printing_Date' Ascending='False'/></OrderBy>";

            queryInfo.ViewFields = @"<FieldRef Name='Id'/><FieldRef Name='ContentType'/><FieldRef Name='Document_Radicado'/><FieldRef Name='Created'/><FieldRef Name='Document_Documental_Type'/><FieldRef Name='Document_SendDest'/><FieldRef Name='ServerUrl'/>";

            queryInfo.Webs = "<Webs Scope='SiteCollection'/>";

            queryInfo.RowLimit = 5000;

            CrossListQueryCache queryCache = new CrossListQueryCache(queryInfo);

            DataTable results = queryCache.GetSiteData(SPContext.Current.Site, CrossListQueryCache.ContextUrl());
            return results.Rows.Count;
        }

        #region Private Methods

        private static RadicadoBaseSalida getRadicadoEntity(DataRow currentRow)
        {
            return new RadicadoBaseSalida
            {
                Id = int.Parse(currentRow[CustomSiteColumns.FIELD_SP_ID].ToString()),
                NoRadicado = currentRow[CustomSiteColumns.FIELD_DOCUMENT_RADICADO].ToString(),
                Created = DateTime.Parse(currentRow[CustomSiteColumns.FIELD_SP_CREATED].ToString()),
                TipoDocumento = currentRow[CustomSiteColumns.FIELD_DOCUMENT_DOCUMENTAL_TYPE].ToString(),
                RemitenteDestinatario = currentRow[CustomSiteColumns.FIELD_DOCSET_SENDERRECEPT].ToString(),
                Path = currentRow[CustomSiteColumns.FIELD_SP_SERVER_URL].ToString(),
                Impreso = currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_PRINTED] == null || string.IsNullOrEmpty(currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_PRINTED].ToString()) ? false : currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_PRINTED].ToString() == "1",
                Incluido = currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_FILED] == null || string.IsNullOrEmpty(currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_FILED].ToString()) ? false : currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_FILED].ToString() == "1",
                RecibidoCorrespondencia = currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_WINDOW] == null || string.IsNullOrEmpty(currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_WINDOW].ToString()) ? false : currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_WINDOW].ToString() == "1",
                Enviado = currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_SENT] == null || string.IsNullOrEmpty(currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_SENT].ToString()) ? false : currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_SENT].ToString() == "1",
                Devuelto = currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_RETURNED] == null || string.IsNullOrEmpty(currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_RETURNED].ToString()) ? false : currentRow[CustomSiteColumns.FIELD_DOCUMENT_STATUS_RETURNED].ToString() == "1"
            };
        }

        private static DataTable getPrintedRadicados(string userLibraryId, string filedLibrary)
        {
            SPSiteDataQuery queryInfo = new SPSiteDataQuery();
            List<string> listsIds = new List<string>() { userLibraryId, filedLibrary };
            List<string> fieldsView = new List<string>() {  CustomSiteColumns.FIELD_SP_ID, 
                                                            CustomSiteColumns.FIELD_SP_CONTENTTYPE, 
                                                            CustomSiteColumns.FIELD_DOCUMENT_RADICADO, 
                                                            CustomSiteColumns.FIELD_SP_CREATED, 
                                                            CustomSiteColumns.FIELD_DOCUMENT_DOCUMENTAL_TYPE, 
                                                            CustomSiteColumns.FIELD_DOCSET_SENDERRECEPT,
                                                            CustomSiteColumns.FIELD_SP_SERVER_URL,
                                                            CustomSiteColumns.FIELD_DOCUMENT_STATUS_PRINTED,
                                                            CustomSiteColumns.FIELD_DOCUMENT_STATUS_WINDOW,
                                                            CustomSiteColumns.FIELD_DOCUMENT_STATUS_SENT,
                                                            CustomSiteColumns.FIELD_DOCUMENT_STATUS_RETURNED,
                                                            CustomSiteColumns.FIELD_DOCUMENT_STATUS_FILED };
            queryInfo.Lists = QuerySiteHelper.GetListIds(listsIds);
            queryInfo.ViewFields = QuerySiteHelper.GetViewFields(fieldsView, GlobalConstants.CAML_FIELD_TYPE_ITEM_FIELD);
            queryInfo.Query = "<Where><IsNotNull><FieldRef Name='Document_Printing_Date' /></IsNotNull></Where>";
            queryInfo.RowLimit = 5000;
            DataTable results = SPContext.Current.Web.GetSiteData(queryInfo);
            return results;
        }

        private static DocumentoImpreso SetPrintDateRadicado(string library, int id, ref string radPath, ref string path, ref SPFileCollection attachedFiles, ref SPFolder foundItem)
        {

            DocumentoImpreso printedRegistry = null;

            SPList targetList = SPContext.Current.Web.Lists.TryGetList(library);
            if (targetList == null) 
                throw new Exception(string.Format("La biblioteca {0} no existe en el sistema", library));

            SPListItem targetItem = targetList.Items.GetItemById(id);
            if (targetItem == null) 
                throw new Exception(string.Format("El documento con id {0} no existe en la biblioteca {1}", id, library));

            if (targetItem[CustomSiteColumns.FIELD_DOCUMENT_PRINTDATE] == null)
            {
                //Update current item
                updatePrintedItem(targetItem, library);

                //Adding new printing entity
                printedRegistry = convertToPrintedDocument(targetItem, library);
                savePrintedEntity(printedRegistry);
            }
            else 
            {
                logPrintedItem(targetItem, library);
            }

            radPath = targetItem.Url;
            foundItem = SPContext.Current.Web.GetFolder(radPath);

            //Get Main Document
            var mainDocument = (from file in foundItem.Files.OfType<SPFile>()
                                where file.Item[CustomSiteColumns.FIELD_DOCUMENT_IS_MAIN] != null && Convert.ToBoolean(file.Item[CustomSiteColumns.FIELD_DOCUMENT_IS_MAIN])
                                select file).FirstOrDefault();
            path = SPContext.Current.Web.Url+"/"+mainDocument.Url;

            return printedRegistry;
        }

        private static void logPrintedItem(SPListItem targetItem, string library)
        {
            SPContext.Current.Web.AllowUnsafeUpdates = true;
            targetItem.Log(library, DateTime.Now, TraceableOperation.Impreso, SPContext.Current.Web.CurrentUser.LoginName, string.Empty);
            targetItem.Update();
            SPContext.Current.Web.AllowUnsafeUpdates = false;
        }

        private static void updatePrintedItem(SPListItem targetItem, string library)
        {
            SPContext.Current.Web.AllowUnsafeUpdates = true;
            targetItem[CustomSiteColumns.FIELD_DOCUMENT_PRINTDATE] = DateTime.Now;
            targetItem[CustomSiteColumns.FIELD_DOCUMENT_STATUS_PRINTED] = true;
            targetItem.Log(library, DateTime.Now, TraceableOperation.Impreso, SPContext.Current.Web.CurrentUser.LoginName, string.Empty);
            targetItem.Update();
            SPContext.Current.Web.AllowUnsafeUpdates = false;
        }

        private static DocumentoImpreso convertToPrintedDocument(SPListItem printedItem, string library)
        {
            DocumentoImpreso printedRegistry = new DAL.DocumentCenter.DocumentoImpreso
            {
                Asunto = printedItem[CustomSiteColumns.FIELD_DOCSET_ASUNTO].ToString(),
                BibliotecaDelDocumento = library,
                IdDocumento = printedItem.ID,
                NoRadicado = printedItem[CustomSiteColumns.FIELD_DOCUMENT_RADICADO].ToString(),
                RemitenteDestinatario = printedItem[CustomSiteColumns.FIELD_DOCSET_SENDERRECEPT].ToString(),
                TipoDocumento = printedItem[CustomSiteColumns.FIELD_DOCUMENT_DOCUMENTAL_TYPE].ToString(),
                Title = string.Format("Impresión para el radicado {0} el día {1:dddd MM yyyy}", printedItem[CustomSiteColumns.FIELD_DOCUMENT_RADICADO].ToString(), DateTime.Now),
                AreaDelDocumento = PeopleHelper.GetPropertyUserProfile(GlobalConstants.UP_DEPARTMENT, printedItem[CustomSiteColumns.FIELD_DOCUMENT_RADICADOR].ToString()),
                Pais = printedItem[CustomSiteColumns.FIELD_DOCUMENT_COUNTRY] as TaxonomyFieldValue
            };

            return printedRegistry;
        }

        private static void savePrintedEntity(DocumentoImpreso printedEntity)
        {
            using (var dc = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                dc.DocumentosImpresos.InsertOnSubmit(printedEntity);
                dc.SubmitChanges();
            } 
        }

        #endregion
    }
}